package pac

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"os/exec"
	"reflect"
	"regexp"
	db "slgw_web/application/gormdb"
	"slgw_web/serial/dto"
	"slgw_web/serial/util"
	"strconv"
	"strings"
	"time"

	"github.com/Knetic/govaluate"
	"github.com/jacobsa/go-serial/serial"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	models "openzbox.com/frame/echo/models/sl_gw01"
	"openzbox.com/protocol/modbus"
)

func init() {
	port, err := ATClient()
	if err == nil {
		util.ICCIDValue = GetICCID(port)
		util.IMEIValue = GetIMEI(port)
		port.Close()
	} else {
		fmt.Println("AT指令串口打开失败:", err)
	}
	//fmt.Println("util.ICCIDValue", util.ICCIDValue)
	// if util.ICCIDValue == "error" {
	// 	util.Error("读取ICCID失败,将导致项目无法正常上报云平台,请重新配置并重启")
	// }
}
func TcpConnect() {
	NetConnect()
	//triggerChan <- true //通知一次
	//triggerChan0 <- true
	for _, sb := range util.DeviceInfo {
		if sb.IsReportedData == 1 {
			if sb.ApplicationLayerProtocol == 1 || sb.ApplicationLayerProtocol == 2 || sb.ApplicationLayerProtocol == 6 {
				if sb.Conn != nil {
					TcpC(sb)
				}
			} else if sb.ApplicationLayerProtocol == 3 || sb.ApplicationLayerProtocol == 4 {
				//if util.MqttClient != nil {
				if sb.MQTTClient != nil {
					TcpC(sb)
				}
			} else if sb.ApplicationLayerProtocol == 5 {
				//modbus
				if len(sb.ModbusTCPClient) > 0 {
					TcpC(sb)
				}
			}
			//首次添加断点续传设备
			rereportedTagList := dto.RereportedTagList{
				DeviceInfo_ID: sb.ID,
				RereportedDay: 0,
			}
			util.RereportedTag = append(util.RereportedTag, rereportedTagList)
		}
	}
	//fmt.Println("util.RereportedTag0", util.RereportedTag)
	select {}
}
func TcpC(sb models.DeviceInfo) {
	sbCopy := sb // 创建局部副本

	if sbCopy.ApplicationLayerProtocol == 1 {
		var serialNum = sbCopy.DeviceInfoID

		var firstStr = "01"
		//var serialNum = "202306250101"
		// var userdata = EncodeToString("89860470192091129393,SL-GW02_20220419")
		var userdata = EncodeToString(util.ICCIDValue + "," + util.Version)
		var hexStr = CalculateChecksum(firstStr + serialNum + userdata)
		lenC := strconv.FormatInt(int64((len(firstStr)+len(serialNum)+len(userdata))/2), 16)
		var topStr = "6800" + lenC + "68"
		var inputInfo = topStr + firstStr + serialNum + userdata + hexStr + "16"
		//先建立连接
		//fmt.Println("inputInfo", inputInfo)
		SendData(inputInfo, sbCopy)
		util.Error(sbCopy.Name + "," + sbCopy.DeviceInfoID + "发送登陆包")
		ReadConn(sbCopy) //第一次需要主动读取
		//开启一个定时上报任务
		CreateTimer(sbCopy.DeviceInfoID+util.Task2, time.Duration(sbCopy.SPITV)*time.Minute, "", 2, sbCopy, nil, nil) //分
		time.Sleep(2 * time.Second)
	} else if sbCopy.ApplicationLayerProtocol == 2 {
		// dtu透传，只需要心跳包
		Task2(sb.DeviceInfoID, sb)
		DTUConnect(sbCopy)
	} else if sbCopy.ApplicationLayerProtocol == 3 || sbCopy.ApplicationLayerProtocol == 4 {
		//mqtts_发布
		CreateTimer(sbCopy.DeviceInfoID+util.Task8, time.Duration(sbCopy.SPITV)*time.Minute, "", 8, sbCopy, nil, nil) //分
	} else if sbCopy.ApplicationLayerProtocol == 5 {
		//modbus
		WriteModbusTCPData(sbCopy)                                                                                    //先直接触发一次,把上次记录写入
		CreateTimer(sbCopy.DeviceInfoID+util.Task9, time.Duration(sbCopy.SPITV)*time.Second, "", 9, sbCopy, nil, nil) //秒
	} else if sbCopy.ApplicationLayerProtocol == 6 {
		//集中器
		// 先发登录包
		paramsLogin := make(map[string]interface{})
		paramsLogin["IMEI"] = ""
		paramsLogin["ICCID"] = util.ICCIDValue
		paramsLogin["SVer"] = util.Version
		paramsLogin["HVer"] = util.HVer
		paramsLogin["RT"] = ""
		paramsLogin["EC"] = ""
		paramsLogin["PVer"] = util.LoginPVer
		//paramsC := make([]util.Concentrator_SendData, 0)
		for _, c := range util.DeviceInfo_Concentrator {
			if c.Device_ID == sbCopy.ID {
				params := util.Concentrator_SendData{Func: 1, Dev: c.Dev, Data: paramsLogin}
				// jsonData, err := json.Marshal(paramsC)
				jsonData, err := json.Marshal(params)
				if err != nil {
					util.Error(sbCopy.Name + ",dev:" + c.Dev + " 发送登录包失败 ,Error encoding JSON:" + err.Error())
					continue
				} else {
					//fmt.Println("jsonData", string(jsonData))
					SendDataByte(jsonData, sbCopy)
					util.Error(sbCopy.Name + ",dev:" + c.Dev + " 发送登陆包")
					//time.Sleep(1 * time.Second)
					//ReadConn(sbCopy) //第一次需要主动读取
				}
				//paramsC = append(paramsC, params)
			}
		}
		//发送心跳包
		//time.Sleep(5 * time.Second)
		Task2(sb.DeviceInfoID, sb)
		//开启定时上报
		CreateTimer(strconv.FormatInt(sbCopy.ID, 10)+util.Task2, time.Duration(sbCopy.SPITV)*time.Minute, "", 11, sbCopy, nil, nil) //分

	}
	if sbCopy.ApplicationLayerProtocol == 1 || sbCopy.ApplicationLayerProtocol == 2 || sbCopy.ApplicationLayerProtocol == 6 {
		//fmt.Println(util.TPITV, sbCopy.SPITV, sbCopy.OHRT)
		//定时读取
		CreateTimer(sbCopy.DeviceInfoID+util.Task4, 1*time.Second, "", 3, sbCopy, nil, nil)
	}

}

// 上行连接初始化
func NetConnect() {
	time.Sleep(60 * time.Second)
	db := db.GetDB()
	var deviceInfo []models.DeviceInfo
	db.Find(&deviceInfo)
	var deviceInfoDetail []models.DeviceInfo_Detail
	db.Where("ModbusTCPType is not null ").Find(&deviceInfoDetail)
	for i, item := range deviceInfo {
		if item.IsReportedData == 1 {
			//if item.DeviceInfoID == "002023110501" {
			if item.ApplicationLayerProtocol == 1 || item.ApplicationLayerProtocol == 2 || item.ApplicationLayerProtocol == 6 {
				conn, err := net.DialTimeout("tcp", item.IP+":"+item.PORT, 10*time.Second)
				if err != nil {
					// 连接的时候出现错误
					//判断是否已连接
					for {
						conn, err = net.DialTimeout("tcp", item.IP+":"+item.PORT, 10*time.Second)
						if err != nil {
							util.Error("Name:" + item.Name + ",ip:" + item.IP + "的tcp连接错误,正在重连,错误:" + err.Error())
							time.Sleep(1 * time.Second)
						} else {
							break
						}
					}

				}
				deviceInfo[i].Conn = conn
			} else if item.ApplicationLayerProtocol == 3 || item.ApplicationLayerProtocol == 4 {
				//mqtts
				if item.OHRT < 60 {
					item.OHRT = 60
				}
				mc := MqttThd(deviceInfo[i])
				deviceInfo[i].MQTTClient = mc
			} else if item.ApplicationLayerProtocol == 5 {
				//modbus
				if len(deviceInfoDetail) > 0 {
					nodeRegisterList := ModbusTCPCServer(deviceInfo[i], deviceInfoDetail)
					deviceInfo[i].ModbusTCPClient = nodeRegisterList

				}
			}
		} else {
			util.Error("Name:" + item.Name + ",已配置不进行上报")
		}
		//}
	}
	util.DeviceInfo = deviceInfo
	//fmt.Println("util.DeviceInfo", util.DeviceInfo)
}

// func NetConnect2() {
// 	//time.Sleep(60 * time.Second)
// 	db := db.GetDB()
// 	var deviceInfo []models.DeviceInfo
// 	db.Find(&deviceInfo)
// 	for i, item := range deviceInfo {
// 		if item.IsReportedData == 1 {
// 			//if item.DeviceInfoID == "002023110501" {
// 			if item.ApplicationLayerProtocol == 1 || item.ApplicationLayerProtocol == 2 {
// 				conn, err := net.DialTimeout("tcp", item.IP+":"+item.PORT, 10*time.Second)
// 				if err != nil {
// 					// 连接的时候出现错误
// 					//判断是否已连接
// 					for {
// 						if item.IP+":"+item.PORT
// 						conn, err = net.DialTimeout("tcp", item.IP+":"+item.PORT, 10*time.Second)
// 						if err != nil {
// 							util.Error("Name:" + item.Name + ",ip:" + item.IP + "的tcp连接错误,正在重连,错误:" + err.Error())
// 							time.Sleep(1 * time.Second)
// 						} else {
// 							break
// 						}
// 					}

// 				}
// 				deviceInfo[i].Conn = conn
// 			} else if item.ApplicationLayerProtocol == 3 || item.ApplicationLayerProtocol == 4 {
// 				//mqtts
// 				if item.OHRT < 60 {
// 					item.OHRT = 60
// 				}
// 				mc := MqttThd(deviceInfo[i])
// 				deviceInfo[i].MQTTClient = mc
// 			}
// 		} else {
// 			util.Error("Name:" + item.Name + ",已配置不进行上报")
// 		}
// 		//}
// 	}
// 	util.DeviceInfo = deviceInfo
// 	//fmt.Println("util.DeviceInfo", util.DeviceInfo)
// }

// 发送信息
func SendData(inputInfo string, sb models.DeviceInfo) {
	//fmt.Println("定时上报的数据：", inputInfo)
	bytes, err := hex.DecodeString(inputInfo)
	if err != nil {
		util.Error("DecodeString转换错误:" + err.Error())
		return
	}
	SendDataByte(bytes, sb)
}

func SendDataByte(bytes []byte, sb models.DeviceInfo) {
	time.Sleep(50 * time.Millisecond)
	for _, sbnew := range util.DeviceInfo {
		if sb.ID == sbnew.ID {
			sb = sbnew
		}
	}
	_, err := sb.Conn.Write(bytes) // 发送数据
	if err != nil {
		util.Error("发送TCP信息错误,10秒后将重启:" + err.Error())
		//重启
		// RestartProject()
		RestartTCPSoft(sb.Conn)
	}

}

// 读取数据
func ReadConn(sb models.DeviceInfo) {
	buffer := make([]byte, 1024)
	for _, sbnew := range util.DeviceInfo {
		if sb.ID == sbnew.ID {
			sb = sbnew
		}
	}

	bytesRead, err := sb.Conn.Read(buffer)
	if err != nil {
		util.Error(sb.Name + " 读取TCP数据错误,10秒后将重启:" + err.Error())
		//重启
		RestartTCPSoft(sb.Conn)
	} else {
		// 有数据可读
		if sb.ApplicationLayerProtocol == 1 {
			//slianyun

			ss := buffer[:bytesRead]
			hexString := hex.EncodeToString(ss)
			hexString = strings.ToLower(hexString)

			//fmt.Println("接收到的信息", sb.Conn, sb.Name, hexString)
			if len(hexString) < 22 {
				util.Error("读取" + sb.Name + "的tcp的数据有误hexString:" + hexString)
				return
			}
			deviced := hexString[10:22]
			first := strings.ToLower(hexString[8:10])
			// res1 := strings.Contains(hexString, "6800086802")
			if first == "02" {
				if hexString[22:24] == "01" {
					//开启心跳包
					Task2(sb.DeviceInfoID, sb)
				} else {

					util.Error("连接失败，系列号未注册")
				}
			} else if first == "05" {
				//请求实时数据
				//GetDataTime() 不能用这个 不然会卡死
				collectData := TaskReportedData(sb, 2)
				var data []models.CollectData
				var d models.CollectData
				d.ID = 1
				// d.DeviceInfoID = sb.ID
				d.Data = collectData
				d.CreateTime = time.Now().Format("2006-01-02 15:04:05")
				data = append(data, d)
				//fmt.Println("data", data)
				//实时响应
				ProcessChunk(data, "06", sb)
			} else if first == "07" {
				//请求历史数据
				timeUnix := hexString[22:30]     //时间 十六进制
				timeDec := HexToDec(timeUnix)    //时间 转为十进制
				time := TimeStampToTime(timeDec) //时间戳转为时间格式
				pageSizeUnix := hexString[30:32]
				pageSize := HexToDec(pageSizeUnix) //条数
				if pageSize > 0 {
					numStr := fmt.Sprintf("%d", pageSize)
					sbID := fmt.Sprintf("%d", sb.ID)
					sqlParm := "SELECT Data,CreateTime FROM CollectData where CreateTime > '" + time + "'  and Device_ID= " + sbID + " order by CreateTime asc limit " + numStr
					//应答历史数据
					ReportedDataSql(sqlParm, "08", sb)
				}
			} else if first == "0a" {
				//上报确认
				if util.IsRereported == 1 {

					time.Sleep(100 * time.Millisecond)
					db := db.GetDB()
					var collectData models.CollectData
					// times := time.Now().Add(-1 * time.Hour).Format("2006-01-02 15:04:05")
					//查询最近的一条 and CreateTime >= ?
					result := db.Where("DeviceInfoID = ? ", sb.DeviceInfoID).Limit(1).Find(&collectData)
					//fmt.Println("collectData_1", collectData)
					if result.Error == nil && collectData.ID != 0 {
						//有值,删除
						db.Delete(&collectData)
					}
				}
			} else if first == "0b" {
				//请求配置参数
				decStr := hexString[22 : len(hexString)-4] //需要解析的参数
				str := DecodeToString(decStr)
				str1 := strings.Replace(str, "YN+", "", -1)
				fmt.Println("str", str)
				fmt.Println("str1", str1)
				userdata := "01"
				if len(str1) > 0 {
					db := db.GetDB()
					for _, item := range strings.Split(str1, ";") { //SPITV=10;PITV=2;
						if item != "" {
							if strings.Contains(item, "=") {
								code := strings.Split(item, "=")[0]  //SPITV
								value := strings.Split(item, "=")[1] //10
								if code == "SPITV" {
									checkValue, err := strconv.ParseInt(value, 10, 64) //转为int64类型
									if err != nil {
										userdata = "02"
										break //跳出for循环，不影响主线程
									}
									StopTimer(sb.DeviceInfoID + util.Task2)
									CreateTimer(sb.DeviceInfoID+util.Task2, time.Duration(checkValue)*time.Minute, "", 2, sb, nil, nil)
								} else if code == "OHRT" {
									StopTimer(sb.DeviceInfoID + util.Task1)
									sb.OHRT, _ = strconv.ParseInt(value, 10, 64)
									Task2(deviced, sb)
								} else if strings.ToLower(code) == "time" {
									result := SetTime(value)
									if !result {
										userdata = "02"
									}
									// result := ChangeTimeS(value)
									// //SetTime(value)
									// if result != "" {
									// 	userdata = "02"
									// }

								}

								// else if code == "IP" {
								//stmt, _ = db.Prepare("UPDATE DeviceInfo SET IP = ? WHERE id = ?")
								// } else if code == "PORT" {
								// 	//stmt, _ = db.Prepare("UPDATE DeviceInfo SET PORT = ? WHERE id = ?")
								// }
								db.Model(&sb).Update(code, value)
							} else {
								if item == "RST" {
									//重启
									Reboot()
								}
							}
						}
					}

				} else {
					userdata = "02"
				}

				serialNum := sb.DeviceInfoID
				length := int64((len(userdata) + 14) / 2)
				lengthHex := FourZero(ToHex(length))
				firstStr := "0C"
				hexStr := CalculateChecksum(firstStr + serialNum + userdata)
				input := "68" + lengthHex + "68" + firstStr + serialNum + userdata + hexStr + "16"
				// fmt.Println("input", input)
				SendData(input, sb)
			} else if first == "0f" {
				//透传命令
				decStr := hexString[22 : len(hexString)-4] //需要解析的参数
				str := DecodeToString(decStr)
				str1 := strings.Replace(str, "YN+", "", -1)
				//fmt.Println("str", str)
				//fmt.Println("str1", str1)
				//userdata := "01"
				ok := ""
				no := ""
				nfc := ""
				for _, char := range "OK" {
					ok += fmt.Sprintf("%02X", char)
				}
				for _, char := range "NO" {
					no += fmt.Sprintf("%02X", char)
				}
				for _, char := range "NO Found COM" {
					nfc += fmt.Sprintf("%02X", char)
				}
				userdata := ok
				if len(str1) > 0 {
					db := db.GetDB()
					for _, item := range strings.Split(str1, ";") { //SPITV=10;PITV=2;
						if item != "" {
							if strings.Contains(item, "=") {
								code := strings.ToUpper(strings.Split(item, "=")[0]) //SPITV
								value := strings.Split(item, "=")[1]                 //10
								fmt.Println("code", code)
								fmt.Println("value", value)
								if code == "SPITV" {
									checkValue, err := strconv.ParseInt(value, 10, 64) //转为int64类型
									if err != nil {
										userdata = "02"
										break //跳出for循环，不影响主线程
									}
									StopTimer(sb.DeviceInfoID + util.Task2)
									CreateTimer(sb.DeviceInfoID+util.Task2, time.Duration(checkValue)*time.Minute, "", 2, sb, nil, nil)
									db.Model(&sb).Update(code, value)
								} else if code == "OHRT" {
									StopTimer(sb.DeviceInfoID + util.Task1)
									sb.OHRT, _ = strconv.ParseInt(value, 10, 64)
									Task2(deviced, sb)
									db.Model(&sb).Update(code, value)
								} else if code == "FTPIP" || code == "FTPPORT" || code == "FTPUN" || code == "FTPPW" || code == "FTPFN" || code == "FTPMOD" {
									db.Model(&models.SysUpgrade{}).Where(1 == 1).Update(code, value)
								} else if code == "TCDATA" {
									if len(strings.Split(value, ",")) != 3 {
										userdata = no
									} else {
										comPort := strings.Split(value, ",")[0] //串口名称
										types := strings.Split(value, ",")[1]   //命令类型 0：字符串 1：十六进制形式发
										values := strings.Split(value, ",")[2]  //命令

										systemInfo := models.SystemInfo{}
										db.First(&systemInfo)
										comType := 1
										if systemInfo.ID != 0 {
											comType = systemInfo.ComType
										}
										comName := GetDeviceName(comPort, comType) //a获取对应的串口名称

										// comName := comPort //测试 获取对应的串口名称
										userdata = nfc
										if comName == "error" {
											userdata = no
										} else {
											util.StopRestart = true
											time.Sleep(6 * time.Second)
											var port io.ReadWriteCloser
											var options serial.OpenOptions

											ctype := 0 // 0:modbus 1:dlt645 2:cj188
											for ti, _ := range Test {
												if Test[ti].ComName == comName {
													//找到对应的串口连接
													//先关闭原先的串口连接
													if Test[ti].ClientClient != nil { //modbusRTu
														Test[ti].ClientClient.Close()

														if rtuProvider, ok := Test[ti].P.(*modbus.RTUClientProvider); ok {
															// 获取串口地址
															rtuProvideroptions := rtuProvider.Config
															//fmt.Println("rtuProvideroptions", rtuProvideroptions)
															var parityMode serial.ParityMode
															if rtuProvideroptions.Parity == "N" {
																parityMode = 0

															} else if rtuProvideroptions.Parity == "O" {
																parityMode = 1
															} else {
																parityMode = 2
															}
															// //重新打开一个串口连接写入
															options = serial.OpenOptions{
																BaudRate:              uint(rtuProvideroptions.BaudRate),
																DataBits:              uint(rtuProvideroptions.DataBits),
																StopBits:              uint(rtuProvideroptions.StopBits),
																InterCharacterTimeout: 100,
																PortName:              comName,
																ParityMode:            parityMode,
																//MinimumReadSize: 0,
															} //初始化结构体变量

														} else {
															userdata = no
															break
														}

													} else if Test[ti].Port != nil { //DLT645
														ctype = 1
														Test[ti].Port.Close()
														options = Test[ti].Options
													} else if Test[ti].CJ188Port != nil { //CJ188
														ctype = 2
														Test[ti].CJ188Port.Close()
														options = Test[ti].Options
													}
													if options == (serial.OpenOptions{}) {
														s := ""
														for _, char := range "options is null" {
															s += fmt.Sprintf("%02X", char)
														}
														userdata = s
													} else {
														//打开新的串口
														port, err = serial.Open(options)
														if err != nil {
															errStr := "PortName:" + comName + ",串口开启失败:" + err.Error()
															util.Error(errStr)
															str, errS2 := stringToGB2312(errStr)
															if errS2 != nil {
																userdata = no
															} else {
																userdata = str
															}
															break
														}
														//发送透传指令
														if types == "0" {
															port.Write([]byte(values))
															//fmt.Println("[]byte(values)", []byte(values))
														} else {
															requestBytes, _ := hex.DecodeString(values)
															port.Write([]byte(requestBytes))
															//fmt.Println("[]byte(requestBytes)", []byte(requestBytes))
														}

														//写入完关闭现有的连接
														port.Close()
														time.Sleep(6 * time.Second)
														//重启原本的连接
														go func() {
															util.StopRestart = false
															if ctype == 0 {
																RTURestart(Test[ti].DataID)
															} else if ctype == 1 {
																PortRestart(Test[ti].DataID)
															} else if ctype == 2 {
																Cj188Restart(Test[ti].DataID)
															}

														}()
														// for
														userdata = ok
														break

													}
												}

											}
											util.StopRestart = false
										}
									}
								}

							} else {
								if item == "RST" {
									//重启
									go Reboot()
								} else if item == "UPDATE" {
									//升级
									isSuccess, errStr := FTPUpgrade()
									if !isSuccess {
										//fmt.Println("errStr", errStr)
										str, errS2 := stringToGB2312(errStr)
										if errS2 != nil {
											userdata = no
										} else {
											userdata = str
										}
										break
									}
								}
							}
						}
					}

				} else {
					//userdata = ""
					// for _, char := range "NO" {
					// 	userdata += fmt.Sprintf("%02X", char)
					// }
					userdata = no
				}
				util.StopRestart = false
				serialNum := sb.DeviceInfoID
				length := int64((len(userdata) + 14) / 2)
				lengthHex := FourZero(ToHex(length))
				firstStr := "0F"
				hexStr := CalculateChecksum(firstStr + serialNum + userdata)
				input := "68" + lengthHex + "68" + firstStr + serialNum + userdata + hexStr + "16"
				// fmt.Println("input", input)
				SendData(input, sb)
			} else if first == "0d" {
				//请求读取参数
				decStr := hexString[22 : len(hexString)-4] //需要解析的参数
				str := DecodeToString(decStr)
				str1 := strings.Replace(str, "YN+", "", -1)
				str1 = strings.Replace(str1, "=?", "", -1)
				fmt.Println("str1", str1)
				// fmt.Println("sb.id", sb.ID)
				if len(str1) > 0 {
					sendData := ""
					//获取DeviceInfo数据
					deviceList := GetDeviceParameters()
					if len(deviceList) > 0 {
						for _, item := range strings.Split(str1, ";") {
							for _, d := range deviceList {
								if d.ID == sb.ID { //同一个设备
									if item == "IP" {
										sendData += item + ":" + d.IP + ";"
									} else if item == "PORT" {
										sendData += item + ":" + d.PORT + ";"
									} else if item == "OHRT" {
										sendData += item + ":" + strconv.FormatInt(d.OHRT, 10) + ";"
									} else if item == "SPITV" {
										sendData += item + ":" + strconv.FormatInt(d.SPITV, 10) + ";"
									}

								}

							}
							if strings.ToLower(item) == "time" {
								sendData += item + ":" + time.Now().Format("2006-01-02 15:04:05") + ";"
							}

						}
					}
					userdata := EncodeToString(sendData)
					serialNum := sb.DeviceInfoID
					length := int64((len(userdata) + 14) / 2)
					lengthHex := FourZero(ToHex(length))
					firstStr := "0E"
					hexStr := CalculateChecksum(firstStr + serialNum + userdata)
					input := "68" + lengthHex + "68" + firstStr + serialNum + userdata + hexStr + "16"
					// fmt.Println("input", input)
					SendData(input, sb)
				}
			}
		} else if sb.ApplicationLayerProtocol == 2 {
			//dtu透传
			if len(buffer) > 0 {
				ss := buffer[:bytesRead]
				fmt.Println("dtu透传数据写入", string(ss))
				for _, item := range util.DeviceInfo {
					if item.ID == sb.ID {
						if item.DtuReadWriteCloser != nil {
							_, err := item.DtuReadWriteCloser.Write(ss)
							if err != nil {
								util.Error("设备名称‘" + sb.Name + "’写入透传数据出错:" + err.Error())
							}
							fmt.Println("写入dtu成功")
						} else {
							util.Error("设备名称‘" + sb.Name + "’无法写入透传数据，原因：透传连接失败")
						}
					}
				}

			}
		} else if sb.ApplicationLayerProtocol == 6 {
			//集中器
			// ss := buffer[:bytesRead]
			// // hexString := string(ss)
			// // hexString = strings.ToLower(hexString)
			// // fmt.Println("hexString", hexString)
			// err = json.Unmarshal(ss, &util.Concentrator_Data)
			// if err != nil {
			// 	util.Error("读取 " + sb.Name + " 的tcp的数据反序列化有误hexString:" + string(ss) + ",err:" + err.Error())

			// } else {
			// 	if util.Concentrator_Data.Func == 129 {
			// 		//登录包成功
			// 		fmt.Println("util.Concentrator_Data1", util.Concentrator_Data)
			// 	} else if util.Concentrator_Data.Func == 130 {
			// 		//心跳包返回数据
			// 		fmt.Println("util.Concentrator_Data2", util.Concentrator_Data)
			// 	}
			// }
			db := db.GetDB()
			now, _ := time.Parse("2006-01-02 15:04:05", time.Now().Format("2006-01-02 15:04:05"))
			// 将新读取的数据追加到已有的数据后面
			var accumulatedData []byte
			accumulatedData = append(accumulatedData, buffer[:bytesRead]...)
			// 解析 JSON 对象
			for {
				startIndex := bytes.IndexByte(accumulatedData, '{')
				if startIndex == -1 {
					// 没有找到 '{'，说明没有更多 JSON 对象
					break
				}

				// 截取包含 '}' 的部分
				accumulatedData = accumulatedData[startIndex+1:]
				// 查找 JSON 对象的结束 '}' 索引
				//endIndex := bytes.Index(accumulatedData, []byte("}{"))
				endIndex := bytes.IndexByte(accumulatedData, '}')
				if endIndex == -1 {
					// JSON 对象未完成，继续等待更多数据
					break
				}

				// 截取整个 JSON 对象
				jsonObject := accumulatedData[:endIndex+1]
				j := "{" + string(jsonObject) + "}"
				//fmt.Println("jsonObject:", j)
				err = json.Unmarshal([]byte(j), &util.Concentrator_Data)
				if err != nil {
					util.Error(sb.Name + "反序列化返回数据出现错误:" + err.Error())
					break
				}
				// 处理 JSON 对象
				//fmt.Println("Received JSON:", util.Concentrator_Data)
				//上报确认
				if util.IsRereported == 1 {

					var collectData models.CollectData
					// times := time.Now().Add(-1 * time.Hour).Format("2006-01-02 15:04:05")
					//查询最近的一条 and CreateTime >= ?
					//.Order("CreateTime desc")
					result := db.Where("ConcentratorDev = ? ", util.Concentrator_Data.Dev).Limit(1).Find(&collectData)
					//fmt.Println("collectData_1", collectData)
					if result.Error == nil && collectData.ID != 0 {
						//有值,删除
						db.Delete(&collectData)
					}
				}
				// 更新 accumulatedData，去掉已经处理过的部分
				accumulatedData = accumulatedData[endIndex+1:]

			}
			if util.Concentrator_Data.Func == 130 && util.Concentrator_Data.Data.DT != "" {
				//心跳包
				// 解析待比较的时间字符串
				targetTimeStr := util.Concentrator_Data.Data.DT
				targetTime, err := time.Parse("2006-01-02 15:04:05", targetTimeStr)
				if err != nil {
					util.Error(sb.Name + " 心跳包时间解析失败:" + err.Error())
				} else {
					// 计算时间差
					duration := now.Sub(targetTime)
					// 超过10分钟的更新时钟
					if duration.Minutes() > 10 {
						util.Error("当前时钟：" + time.Now().Format("2006-01-02 15:04:05") + " ,时钟失真，心跳包更新时钟为：" + targetTimeStr)
						err := ChangeTimeS(targetTimeStr)
						if err != "" {
							util.Error("心跳包更新时钟失败：" + err)
						}
					}
				}

			}
		}
	}
}

// 字符串转为GB
func stringToGB2312(input string) (string, error) {
	// 创建 GB2312 编码的编码器
	encoder := simplifiedchinese.GB18030.NewEncoder()

	// 使用编码器将字符串转换为 GB2312 编码
	encodedBytes, _, err := transform.Bytes(encoder, []byte(input))
	if err != nil {
		return "", err
	}

	// 将字节数组转换为十六进制字符串
	hexString := fmt.Sprintf("%X", encodedBytes)
	return hexString, nil
}

// 校时
func SetTime(time string) bool {
	if time != "" {
		util.Error("下控校时时间:" + time)
		// 设置系统时间
		setDateCmd := exec.Command("date", "-s", time)
		err := setDateCmd.Run()
		if err != nil {
			return false
		}

		// 将系统时间同步到RTC
		hwclockCmd := exec.Command("busybox", "hwclock", "--systohc")
		err = hwclockCmd.Run()
		if err != nil {
			return false
		}

	} else {
		return false
	}
	return true //成功
}

// 定时采集数据
func TaskCollectData(t dto.CollectSet) {
	//采集方法
	//go func() {
	if t.ClientClient != nil {
		GetDataTime(t)
	} else if t.Port != nil {
		SendDLT645Data(t) //dlt645
	} else if t.S7Client != nil {
		//西门子s7
		Siemenss7(t)
	} else if t.CJ188Port != nil {
		SendCj188Data(t)
	}

	// data := util.CollectDataList
	// if data != nil {
	// 	util.WriteMessage(data, "1")
	// }
	//fmt.Println("采集数据：", util.CollectDataList)
	//}()
}
func CollectWebsocket() {

	data := util.CollectDataList
	if data != nil {
		util.WriteMessage(data, "1")
	}

	// 输出 JSON 数据
	//fmt.Println("CollectWebsocket", data)
}

// 采集数据缓存到数据库
func AddCollectDataList() {
	data := util.CollectDataList
	if len(data) > 0 {
		jsonData, err := json.Marshal(data)
		if err != nil {
			util.Error("采集数据缓存错误:", err)
		} else {
			list := string(jsonData)
			db := db.GetDB()
			collectDataSession := models.CollectDataSession{}
			db.First(&collectDataSession)
			collectDataSession.CollectDataList = list
			db.Model(&models.CollectDataSession{}).Where("1==1").Updates(&collectDataSession)
		}
	}
}

// 获取网关时间
func GetTime() {
	time := time.Now().Format("2006-01-02 15:04:05")
	util.WriteMessage2(time, "4")
}

// 读取ICCID
func ATClient() (io.ReadWriteCloser, error) {
	portName := "/dev/ttyUSB1"
	if util.ATType == 1 {
		portName = "/dev/ttyUSB2"
	}

	options := serial.OpenOptions{
		BaudRate:              115200,
		DataBits:              8,
		StopBits:              1,
		InterCharacterTimeout: 100,
		PortName:              portName,
		ParityMode:            0,
	}
	port, err := serial.Open(options)
	if err != nil {
		return port, err
	}
	return port, nil
}

func GetICCID(port io.ReadWriteCloser) string {
	fmt.Println("读取ICCID中.....")
	requestBytes := []byte(util.CMD_ICCID)

	_, errW := port.Write(requestBytes)
	if errW != nil {
		fmt.Println("请检查sim卡,读取ICCID错误,发送参数失败:" + errW.Error())
		return "0000000000000000"
	}

	//等待返回数据
	buffer := make([]byte, 0)
	receivedData := false // 标志是否收到数据
	count := 0
	for {

		//time.Sleep(50 * time.Millisecond)
		if count == 20 {
			//port.Close()
			return "0000000000000000"

		}
		buf := make([]byte, 1024)
		if receivedData {

			//成功接收
			str := string(buffer)
			ccid, err := extractStr(str, "CCID:(.+)")
			if err != nil {
				fmt.Println("提取 CCID 失败:", err)
				return "0000000000000000"
			}
			fmt.Println("读取ICCID成功：", ccid)
			buffer = nil
			receivedData = false
			//port.Close()
			return ccid

		}

		n, err := port.Read(buf)
		if err != nil {

			fmt.Println("请检查sim卡,读取ICCID错误,等待返回参数失败:" + err.Error())
			return "0000000000000000"

		} else {

			buf = buf[:n]
			buffer = append(buffer, buf...)

			if strings.Index(string(buffer), "OK") > 0 {
				receivedData = true
			}
		}

		count++
	}
}

func GetIMEI(port io.ReadWriteCloser) string {
	fmt.Println("读取IMEI中.....")
	requestBytes := []byte(util.CMD_IMEI)

	_, errW := port.Write(requestBytes)
	if errW != nil {
		fmt.Println("读取IMEI错误，发送失败:" + errW.Error())
		return "0000000000000000"
	}
	//等待返回数据
	buffer := make([]byte, 0)
	receivedData := false // 标志是否收到数据
	count := 0
	for {
		if count == 20 {
			return "0000000000000000"
		}
		buf := make([]byte, 1024)
		if receivedData {
			//成功接收
			str := string(buffer)
			i := strings.Index(str, "86")
			ss := str[i : i+15]
			fmt.Println("读取IMEI成功：", ss)
			buffer = nil
			receivedData = false
			//port.Close()
			return ss

		}
		n, err := port.Read(buf)
		if err != nil {
			fmt.Println("读取IMEI错误，等待返回参数失败:" + err.Error())
			return "0000000000000000"
		} else {
			buf = buf[:n]
			buffer = append(buffer, buf...)

			if strings.Index(string(buffer), "OK") > 0 {
				receivedData = true
			}
			//fmt.Println("GetIMEI", string(buffer))
			//fmt.Println("n：", n)
		}

		count++
	}
	return "0000000000000000"
}

// 正则获取ccid后的数字
func extractStr(input string, pattern string) (string, error) {
	// 定义正则表达式模式
	//pattern := `CCID:(.+)`
	// 编译正则表达式
	re := regexp.MustCompile(pattern)
	// 在输入字符串中查找匹配项
	matches := re.FindStringSubmatch(input)
	// 如果找到匹配项，则提取 CCID
	if len(matches) > 1 {
		return matches[1], nil
	}
	// 没有找到匹配项
	return "", fmt.Errorf("未找到 CCID")
}

// FTP远程升级
func FTPUpgrade() (bool, string) {
	sysUpgrade := models.SysUpgrade{}
	db := db.GetDB()
	db.First(&sysUpgrade)
	if sysUpgrade.ID == 0 {
		util.Error("下发升级失败,ftp升级数据未填写")
		return false, "下发升级失败,ftp升级数据未填写"
	}
	exe := "wget ftp://" + sysUpgrade.FTPUN + ":" + sysUpgrade.FTPPW + "@" + sysUpgrade.FTPIP + ":" + sysUpgrade.FTPPORT + "/" + sysUpgrade.FTPFN
	if sysUpgrade.FTPMOD == "0" { //匿名登录
		exe = "wget ftp://" + sysUpgrade.FTPIP + ":" + sysUpgrade.FTPPORT + "/" + sysUpgrade.FTPFN
	}
	cmd := exec.Command("sh", "-c", exe)
	fmt.Println("exe", exe)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	err := cmd.Run()
	if err != nil {
		util.Error("下发升级失败" + err.Error())
		return false, "下发升级失败" + err.Error()
	} else {
		//移动文件
		exe2 := "mv " + sysUpgrade.FTPFN + " /app/UpDateFile/GoApp"
		cmd2 := exec.Command("sh", "-c", exe2)
		fmt.Println("exe2", exe2)
		cmd2.Stdout = os.Stdout
		cmd2.Stderr = os.Stderr

		err2 := cmd2.Run()
		if err2 != nil {
			util.Error("下发升级失败" + err.Error())
			return false, "下发升级失败" + err.Error()
		}
	}
	return true, ""
}

// 公式计算
func FunFormula(Formula string) string {
	expression := replaceIdsWithValues(Formula)
	if expression == "Error" {
		return ""
	}
	result := Expression(expression)
	return result
}

// 拆分[] 获取对应id真实数值
func replaceIdsWithValues(expression string) string {
	re := regexp.MustCompile(`\[([0-9]+)\]`)
	error := false
	result := re.ReplaceAllStringFunc(expression, func(match string) string {
		idStr := re.FindStringSubmatch(match)[1]
		id, err := strconv.Atoi(idStr) //获取所有[xx]的id
		if err != nil {
			error = true
			util.Error("表达式解析错误,expression:" + expression + ",err:" + err.Error())
			return match
		}
		value := ""
		for _, item := range util.CollectDataList {
			if item.ID == int64(id) {
				if item.Value2 == nil {
					error = true
				} else {
					value = *item.Value2
				}

			}
		}
		return value
	})
	if error {
		return "Error"
	} else {
		return result
	}
}
func Expression(expression string) string {

	// 解析表达式
	expr, err := govaluate.NewEvaluableExpression(expression)
	if err != nil {
		util.Error("expression:" + expression + ",解析表达式时出错:" + err.Error())
		return ""
	}

	// 准备变量
	variables := map[string]interface{}{}

	// 计算表达式的值
	result, err := expr.Evaluate(variables)
	if err != nil {
		util.Error("expression:" + expression + ",计算表达式值时出错:" + err.Error())
		return ""
	}
	//resultStr := fmt.Sprintf("%.3f", result) //只能最多保留三位
	resultStr := ConvertToString(result)
	//fmt.Sprintf("%v", result)
	return resultStr
}

func ConvertToString(value interface{}) string {
	// 获取值的类型
	valueType := reflect.TypeOf(value)

	// 根据类型执行相应的转换
	switch valueType.Kind() {
	case reflect.Float32:
		// 如果是浮点数，使用 strconv.FormatFloat 进行格式化
		return strconv.FormatFloat(value.(float64), 'f', -1, 32)
	case reflect.Float64:
		return strconv.FormatFloat(value.(float64), 'f', -1, 64)
	default:
		// 默认情况，使用 fmt.Sprintf 将值转换为字符串
		return fmt.Sprintf("%v", value)
	}
}

// 校时
func ChangeTimeS(timeStr string) string {
	if timeStr != "" {
		// 尝试解析字符串
		layout := "2006-01-02 15:04:05"
		_, err := time.Parse(layout, timeStr)
		if err != nil {
			return "输入为:" + timeStr + ",不符合类似时间格式'2006-01-02 15:04:05'"
		}

		// 设置系统时间
		setDateCmd := exec.Command("date", "-s", timeStr)
		err = setDateCmd.Run()
		if err != nil {
			return "Error setting system time:" + err.Error()
		}
		// 将系统时间同步到RTC
		// hwclockCmd := exec.Command("busybox", "hwclock", "--systohc")
		hwclockCmd := exec.Command("busybox", "hwclock", "-u", "-w") //新版
		err = hwclockCmd.Run()
		if err != nil {
			return "Error setting RTC time:" + err.Error()
		}
		return ""
	} else {
		return "time参数未传"
	}
}

// 采集参数高低字节转换 1:AB 2:BA 3:ABCD 4:BADC 5:CDAB 6:DCBA 7:低字节在后 8:低字节在前
func ChangeByte(byteBuffer []byte, ValueStructure *int) []byte {
	result := byteBuffer
	if ValueStructure != nil {
		switch *ValueStructure {
		case int(dto.AB): //默认不变
			result = byteBuffer
		case int(dto.BA):
			if len(byteBuffer) != 2 {
				util.Error("高低字节转换时,byteBuffer长度错误")
				return byteBuffer
			}
			result = []byte{byteBuffer[1], byteBuffer[0]}
		case int(dto.ABCD): //默认不变
			result = byteBuffer
		case int(dto.BADC):
			if len(byteBuffer) != 4 {
				util.Error("高低字节转换时,byteBuffer长度错误")
				return byteBuffer
			}
			result = []byte{byteBuffer[1], byteBuffer[0], byteBuffer[3], byteBuffer[2]}
		case int(dto.CDAB):
			if len(byteBuffer) != 4 {
				util.Error("高低字节转换时,byteBuffer长度错误")
				return byteBuffer
			}
			result = []byte{byteBuffer[2], byteBuffer[3], byteBuffer[0], byteBuffer[1]}
		case int(dto.DCBA):
			if len(byteBuffer) != 4 {
				util.Error("高低字节转换时,byteBuffer长度错误")
				return byteBuffer
			}
			result = []byte{byteBuffer[3], byteBuffer[2], byteBuffer[1], byteBuffer[0]}
		case int(dto.DH): //默认不变
			result = byteBuffer
		// case int(dto.DQ):

		// 	result = []byte{byteBuffer[3], byteBuffer[2], byteBuffer[1], byteBuffer[0]}
		default:
			result = byteBuffer
		}
	}
	return result
}

// 将切片中指定索引的元素移动到最前面
func MoveToFront(slice []models.Serial_Slave_Detail, index int) {
	// 将指定索引的元素移动到切片的最前面
	temp := slice[index]
	copy(slice[1:], slice[:index])
	slice[0] = temp

}

// 定义结构体解析 JSON
type ResponseData struct {
	Data      string `json:"Data"`
	Success   bool   `json:"Success"`
	ErrorCode int    `json:"ErrorCode"`
	Msg       string `json:"Msg"`
}

// 定时校时
func TaskSetTime() {
	defer func() {
		if err := recover(); err != nil {
			util.Error("定时校时出现异常")
		}
	}()
	url := util.TaskSetTimeUrl
	// url := "http://172.0.8.50:6106/api/Orther/GetNowTime"
	// 创建带有超时的 HTTP 客户端
	client := &http.Client{
		Timeout: 5 * time.Second,
	}
	response, err := client.Get(url)
	if err != nil {
		util.Error("定时校时失败:" + err.Error())
		return
	}
	defer response.Body.Close()
	if response.StatusCode != http.StatusOK {
		util.Error("定时校时失败:" + strconv.Itoa(response.StatusCode))
		return
	}
	// 读取响应体
	body, err := io.ReadAll(response.Body)
	if err != nil {
		util.Error("定时校时失败:" + err.Error())
		return
	}
	var result ResponseData
	err = json.Unmarshal(body, &result)
	if err != nil {
		util.Error("定时校时失败:" + err.Error())
		return
	}

	// 输出 Data 字段的值
	util.Error("定时校时,时间:" + result.Data)
	errS := ChangeTimeS(result.Data)
	if errS != "" {
		util.Error("定时校时失败:" + errS)
		return
	}
}
